package cn.lzx;

import cn.lzx.generator.AutoGenerator;
import cn.lzx.generator.DataSourceConfig;
import cn.lzx.generator.GlobalConfig;
import cn.lzx.generator.PackageConfig;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

import java.io.*;
import java.sql.SQLException;
import java.util.Properties;


/**
 * abc项目代码生成器
 */
public class MainApp extends Application {
    private static String profilepath = "config.properties";
    private static Properties props = new Properties();

    static {
        try {
            File file = new File(profilepath);
            if (!file.exists()) {
                file.createNewFile();
                writeFile(profilepath, "filename=\\u8BF7\\u8F93\\u5165\\u751F\\u6210\\u7684\\u5B9E\\u4F53\\u6587" +
                        "\\u4EF6\\u540D\n" +
                        "url=url\n" +
                        "maindir=\\u8FD9\\u91CC\\u586B\\u9879\\u76EEmain\\u6240\\u5728\\u76EE\\u5F55\n" +
                        "bundleId=bundleId\n" +
                        "username=root\n" +
                        "tablename=\\u8868\\u540D\n" +
                        "sessionFactoryID=separatefreeze\n" +
                        "drivername=\\u6570\\u636E\\u5E93\\u9A71\\u52A8\n" +
                        "password=root", false);
            }
            props.load(new FileInputStream(profilepath));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            System.exit(-1);
        } catch (IOException e) {
            System.exit(-1);
        }
    }

    public static void main(String[] args) {
        launch(args);
    }

    public void start(Stage primaryStage) throws Exception {
        Scene scene = new Scene(new Group(), 700, 700);
        scene.getStylesheets().add(getClass().getClassLoader().getResource("application.css")
                .toExternalForm());
        GridPane grid = new GridPane();
        grid.setVgap(8);
        grid.setHgap(20);
        grid.setPadding(new Insets(15, 15, 15, 15));
        grid.add(new Label("GlobalConfig=>"), 0, 0, 2, 1);
        grid.add(new Label("mainDir:"), 0, 1);

        TextField maindir = new TextField();
        maindir.setText(getConfigValue("maindir"));
        maindir.setPrefWidth(400);
        grid.add(maindir, 1, 1);

        grid.add(new Label("DataSourceConfig=>"), 0, 2, 2, 1);
        grid.add(new Label("drivername:"), 0, 3);

        TextField drivername = new TextField(getConfigValue("drivername"));
        grid.add(drivername, 1, 3);

        grid.add(new Label("url:"), 0, 4);
        TextField url = new TextField(getConfigValue("url"));
        grid.add(url, 1, 4);

        grid.add(new Label("username:"), 0, 5);
        TextField username = new TextField(getConfigValue("username"));
        grid.add(username, 1, 5);

        grid.add(new Label("password:"), 0, 6);
        TextField password = new TextField(getConfigValue("password"));
        grid.add(password, 1, 6);

        grid.add(new Label("tablename:"), 0, 7);
        TextField tablename = new TextField(getConfigValue("tablename"));
        grid.add(tablename, 1, 7);

        grid.add(new Label("PackageConfig=>"), 0, 8, 2, 1);
        grid.add(new Label("bundleId:"), 0, 9);

        TextField bundleId = new TextField(getConfigValue("bundleId"));
        grid.add(bundleId, 1, 9);

        grid.add(new Label("sessionFactoryID:"), 0, 10);
        TextField sessionFactoryID = new TextField(getConfigValue("sessionFactoryID"));
        grid.add(sessionFactoryID, 1, 10);

        grid.add(new Label("filename:"), 0, 11);
        TextField filename = new TextField(getConfigValue("filename"));
        grid.add(filename, 1, 11);


        CheckBox entityCheckBox = new CheckBox("实体");
        entityCheckBox.setSelected(true);
        entityCheckBox.selectedProperty().addListener((ov, old_val, new_val) -> System.out.println(entityCheckBox.isSelected()));

        CheckBox xmlCheckBox = new CheckBox("xml");
        xmlCheckBox.setSelected(true);

        CheckBox modelCheckBox = new CheckBox("model");
        modelCheckBox.setSelected(true);

        Button button = new Button("generate");

        HBox hBox = new HBox(10, entityCheckBox, xmlCheckBox, modelCheckBox, button);
        hBox.setSpacing(10);
        grid.add(new Label("whichIsGen:"), 0, 12);
        grid.add(hBox, 1, 12);

        TextArea textArea = new TextArea();
        textArea.setWrapText(true);
        textArea.setPrefWidth(400);
        textArea.setPrefHeight(130);
        grid.add(textArea, 1, 13);

        button.setOnAction(event -> {
            AutoGenerator mpg = new AutoGenerator();
            // 全局配置
            mpg.setEntityCheck(entityCheckBox.isSelected());
            mpg.setXmlCheck(xmlCheckBox.isSelected());
            mpg.setModelCheck(modelCheckBox.isSelected());
            GlobalConfig gc = new GlobalConfig();
            gc.setMainDir(maindir.getText());
            writeProperties("maindir", maindir.getText());
            gc.setFileOverride(true);//是否覆盖
            mpg.setGlobalConfig(gc);

            // 数据源配置
            DataSourceConfig dsc = new DataSourceConfig();
            dsc.setDriverName(drivername.getText());
            writeProperties("drivername", drivername.getText());
            dsc.setUsername(username.getText());
            writeProperties("username", username.getText());
            dsc.setPassword(password.getText());
            writeProperties("password", password.getText());
            dsc.setUrl(url.getText());
            writeProperties("url", url.getText());
            dsc.setTableName(tablename.getText());
            writeProperties("tablename", tablename.getText());
            mpg.setDataSourceConfig(dsc);

            // 包配置
            PackageConfig pc = new PackageConfig();
            pc.setBundleId(bundleId.getText());
            writeProperties("bundleId", bundleId.getText());
            pc.setFileName(filename.getText());
            writeProperties("filename", filename.getText());
            pc.setSessionFactoryID(sessionFactoryID.getText());
            writeProperties("sessionFactoryID",sessionFactoryID.getText());
            mpg.setPackageConfig(pc);
            // 执行生成
            try {
                mpg.execute(textArea);
            } catch (SQLException | IOException e) {
                textArea.setText(e.getMessage());
            }
        });


        Group root = (Group) scene.getRoot();
        root.getChildren().add(grid);

        primaryStage.setTitle("abc实体、xml和model生成器 V1.0.0");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    /**
     * 写文件
     *
     * @param filename 文件名（带路径）
     * @param content  内容
     * @param append   是否追加
     * @throws IOException
     */
    private static void writeFile(String filename, String content, Boolean append) {
        File file = new File(filename);
        try {
            if (!file.exists()) {
                file.createNewFile();
            }
            //写入文件
            FileOutputStream fos = new FileOutputStream(file, append);
            OutputStreamWriter out = new OutputStreamWriter(fos, "utf-8");
            BufferedWriter bw = new BufferedWriter(out);
            bw.write(content);
            bw.write("\r\n");
            bw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取到配置文件信息
     *
     * @param key
     * @return
     */
    private static String getConfigValue(String key) {
        return props.getProperty(key);
    }

    /**
     * 更新（或插入）一对properties信息(主键及其键值)
     * 如果该主键已经存在，更新该主键的值；
     * 如果该主键不存在，则插件一对键值。
     *
     * @param keyname  键名
     * @param keyvalue 键值
     */
    private static void writeProperties(String keyname, String keyvalue) {
        try {
            // 调用 Hashtable 的方法 put，使用 getProperty 方法提供并行性。
            // 强制要求为属性的键和值使用字符串。返回值是 Hashtable 调用 put 的结果。
            OutputStream fos = new FileOutputStream(profilepath);
            props.setProperty(keyname, keyvalue);
            // 以适合使用 load 方法加载到 Properties 表中的格式，
            // 将此 Properties 表中的属性列表（键和元素对）写入输出流
            props.store(fos, "Update '" + keyname + "' value");
        } catch (IOException e) {
            System.err.println("属性文件更新错误");
        }
    }
}